/***********************************************************************************************//**
*\n  @file       spi_ctrl.h
*\n  @brief      SPI控制程序、编码、解码
*\n  @details
*\n -----------------------------------------------------------------------------------
*\n  文件说明：
*\n       1. SPI控制程序、编码、解码
*\n
*\n -----------------------------------------------------------------------------------
*\n  版本:   	修改人:       修改日期:    		描述:
*\n  V0.01  	项目组        2020.2.17        创建
*\n
***************************************************************************************************/

/**************************************************************************************************
* 头文件
***************************************************************************************************/
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <fcntl.h>
#include <string.h>
#include <libgen.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/time.h> 
#include <sys/mman.h>
#include <errno.h>
#include <pthread.h>
#include <semaphore.h>


#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#include "cpu_occupy.h"
#include "fpga_io.h"
#include "spi_ctrl.h"

/**************************************************************************************************
* 宏定义、结构定义
***************************************************************************************************/
#define SPI_DEBUG   	1		     ///< 调试信息开关
#define BUFFER_MAX_SIZE (2 * 1024)   ///< 最大数据长度


/// SPI句柄与操作
typedef struct TSpiHandler
{
	//private:
	const char *name;			///< 句柄名称
	const char *dev_name;		///< 设备节点
	uint8_t    	mode;  			///< 配置模式(SPI_MODE_0:上升沿采样, SPI_MODE_1：下降沿采样)
	uint32_t   	speed;    		///< 波特率 = speed/2  Bps
	uint8_t    	bits;
	uint16_t   	delay;
	int			fd;             ///<  spi设备接口
	pthread_mutex_t   mutex;
	uint8_t     tx_omit_buf[BUFFER_MAX_SIZE];
	uint8_t     rx_omit_buf[BUFFER_MAX_SIZE];

	// interrupt
	const char *uio_name;
	int			uio_fd;         ///<  EMIO中断接口
	sem_t		sem;
	

	//public:
	int (*Lock)    (struct TSpiHandler *this);
	int (*Unlock)  (struct TSpiHandler *this);
	int (*Open)    (struct TSpiHandler *this);
	int (*Close)   (struct TSpiHandler *this);
	int (*Read)    (struct TSpiHandler *this, uint8_t *pRxBuf, int len);
	int (*Write)   (struct TSpiHandler *this, uint8_t *pTxBuf, int len);
	int (*Transfer)(struct TSpiHandler *this, uint8_t *pTxBuf, uint8_t *pRxBuf, size_t size);
}  TSpiHandler;


/**************************************************************************************************
* 全局变量声明、定义
***************************************************************************************************/


/**************************************************************************************************
* 私有变量声明、定义
***************************************************************************************************/
///< uds协议处理的回调函数
static TCallback_UdsProcess tCallback_UdsProcess1 = NULL;
/**************************************************************************************************
* 私有函数声明、定义
***************************************************************************************************/
/// 调试信息
#if SPI_DEBUG
#define PCL_NONE				 "\e[0m"
#define PCL_YELLOW				 "\e[1;33m"
#define PCL_RED 				 "\e[0;31m"

#define dbg_printf(...)   \
	do{ printf(PCL_NONE "[%s,%d,%s] ", __FILE__, __LINE__, __func__); \
		printf(__VA_ARGS__); }while(0)

	
#define dbg_info(buffer,size, ...)   \
	do{ printf(PCL_NONE "[%s,%d,%s] ", __FILE__, __LINE__, __func__); \
			printf(__VA_ARGS__); \
			char *p = (char*)buffer; \
			int ii_; \
			for (ii_=0; ii_<(int)size; ii_++) \
			{   printf("%02x ", *(p++)); \
				if ((ii_ != 0) && (ii_ % 32 == 0)) printf("\n"); \
			} \
			if (ii_ % 32 != 0) printf("\n"); \
	}while(0)

	
#define dbg_warn(...)   \
		do{ printf(PCL_YELLOW "[warn,%s,%d,%s] ", __FILE__, __LINE__, __func__); \
		printf(__VA_ARGS__); }while(0)

#define dbg_error(...)   \
	do{ printf(PCL_RED "[error,%s,%d,%s] ", __FILE__, __LINE__, __func__); \
		printf(__VA_ARGS__); }while(0)

#define dbg_fatal(...)   \
	do{ printf(PCL_RED "[fatal,%s,%d,%s] ", __FILE__, __LINE__, __func__); \
		printf(__VA_ARGS__); }while(0)

#else
#define dbg_error(...)
#define dbg_fatal(...)
#define dbg_warn(...)
#define dbg_printf(...)
#define dbg_info(...)
#endif



// 读取当前时间ms
static int get_timer_now ()
{
    struct timeval now;
    gettimeofday(&now, NULL);
    return(now.tv_sec * 1000 + now.tv_usec / 1000);
}



#define ISO_LAYER2_DATA_LINK   1
#if     ISO_LAYER2_DATA_LINK
/**************************************************************************************************
* 内容说明：
*   1.该部分为SPI链路层协议（ISO layer2 data link）
*   2.该部分包括如下接口，负责链路层数据的收发
*     SpiOpen()       打开
*     SpiClose()      关闭
*     SpiTransfer()   收/发接口
*     SpiRead()       接收接口
*     SpiWrite()      发送接口
*     SpiLock()       互斥上锁
*     SpiUnlock()     互斥解锁
***************************************************************************************************/

/*************************************************************************************//**
*\n 函数名称： OpenHandler()
*\n 功能描述：
*\n            打开spi通信接口
*\n 输入参数：
*\n            TSpiHandler *this  
*\n 输出参数: 
*\n            
*\n 返 回 值: 
*\n           0 成功; -1 失败; -n     错误码   
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.3.15     创建
*****************************************************************************************/
static int OpenHandler(TSpiHandler *this)
{
	int ret;
	if (this->fd > 0)
		return this->fd;

	this->fd = open(this->dev_name, O_RDWR);
	if (this->fd < 0)
	{
		dbg_error("open(%s) error \n", this->dev_name);
		return -1;
	}

	ret = ioctl(this->fd, SPI_IOC_WR_MODE, &(this->mode));
	if (ret != 0)
	{
		dbg_error("can't set spi mode:%s \n", strerror(errno));
		close(this->fd);
		this->fd = -1;
		return -1;
	}
	
	ret = pthread_mutex_init(&this->mutex, NULL);
	if (ret != 0)
	{
		dbg_error("pthread_mutex_init(): %s\n", strerror(errno));
		close(this->fd);
		this->fd = -1;
		return -1;
	}

	return 0;
}

/// 关闭spi
static int CloseHandler(TSpiHandler *this)
{
	if (this->fd > 0)
	{
		close(this->fd);
		this->fd = -1;
		pthread_mutex_destroy(&this->mutex);
	}
	return 0;
}

///  上锁
static int LockHandler(struct TSpiHandler *this)
{
	int ret;
	if (this->fd <= 0)
	{
		dbg_error("%s->fd <= 0 \n", this->name);
		return -1;
	}
	
	ret = pthread_mutex_lock(&this->mutex);
	if (ret != 0)
		return -1;
		
	return  0;
}

/// 开锁
static int UnlockHandler(struct TSpiHandler *this)
{
	int ret;
	if (this->fd <= 0)
	{
		dbg_error("%s->fd <= 0 \n", this->name);
		return -1;
	}
	
 	ret = pthread_mutex_unlock(&this->mutex);
 	if (ret != 0)
 		return -1;
 		
	return  0;
}


/// 同时读/写
static int TransferHandler(TSpiHandler *this, uint8_t *pTxBuf, uint8_t *pRxBuf, size_t size)
{
	int ret;
	struct spi_ioc_transfer tr =
	{
		.tx_buf = (unsigned long) pTxBuf,
		.rx_buf = (unsigned long) pRxBuf,
		.len    = size,
		.delay_usecs    = this->delay,
		.bits_per_word 	= this->bits,
		.speed_hz 		= this->speed,  // 波特率
	};

	if (this->fd <= 0)
	{
		dbg_error("NULL == this || this->fd <= 0 \n");
		return -1;
	}
	if (size > BUFFER_MAX_SIZE)
	{
		dbg_error("size > BUFFER_MAX_SIZE \n");
		return -1;
	}

	if (pTxBuf == NULL)
	{
		memset(this->tx_omit_buf, 0, size);
		tr.tx_buf = (unsigned long) this->tx_omit_buf;
		
	}
	if (pRxBuf == NULL)
	{
		tr.rx_buf = (unsigned long) this->rx_omit_buf; 
	}
	// 同时发送、接收数据
	ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr);
	if (ret < 1)
	{
		dbg_error("can't send spi message \n");
		return -1;
	}

#if SPI_DEBUG
	// 打印接收数据
	uint8_t *pString = (pRxBuf != NULL) ? pRxBuf : this->rx_omit_buf;
	for (int i = 0; i < size; i++) 
	{
		if (i == 0)
		{
			dbg_printf("recv[%d]: ", size);
		}
		printf("%.2x ", pString[i]);
	}
	printf("\n");
#endif

	return 0;

}

/// 写spi
static int WriteHandler(TSpiHandler *this, uint8_t *pTxBuf, int size)
{
	int ret;
	struct spi_ioc_transfer tr =
	{
		.tx_buf = (unsigned long) pTxBuf,
		.rx_buf = (unsigned long) this->rx_omit_buf,  // 忽略接收数据
		.len    = size,
		.delay_usecs    = this->delay,
		.bits_per_word 	= this->bits,
		.speed_hz 		= this->speed,  // 波特率
	};
	if (this->fd <= 0)
	{
		dbg_error("NULL == this || this->fd <= 0 \n");
		return -1;
	}
	if (size > BUFFER_MAX_SIZE)
	{
		dbg_error("size > BUFFER_MAX_SIZE \n");
		return -1;
	}
	
	// 同时发送、接收数据
	ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr);
	if (ret < 1)
	{
		dbg_error("can't send spi message \n");
		return -1;
	}

#if SPI_DEBUG
		// 打印接收数据
		for (int i = 0; i < size; i++) 
		{
			if (i == 0)
			{
				dbg_printf("recv[%d]: ", size);
			}
			printf("%.2x ", this->rx_omit_buf[i]);
		}
		printf("\n");
#endif

	return 0;
}

/// 读spi
static int ReadHandler(TSpiHandler *this, uint8_t *pRxBuf, int size)
{
	int ret;
	struct spi_ioc_transfer tr =
	{
		.tx_buf = (unsigned long) this->tx_omit_buf,  // 忽略发送数据
		.rx_buf = (unsigned long) pRxBuf,
		.len    = size,
		.delay_usecs    = this->delay,
		.bits_per_word 	= this->bits,
		.speed_hz 		= this->speed,  // 波特率
	};

	if (this->fd <= 0)
	{
		dbg_error("NULL == this || this->fd <= 0 \n");
		return -1;
	}
	if (size > BUFFER_MAX_SIZE)
	{
		dbg_error("size > BUFFER_MAX_SIZE \n");
		return -1;
	}
	
	// 同时发送、接收数据
	memset(this->tx_omit_buf, 0, sizeof(this->tx_omit_buf));
	ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr);
	if (ret < 1)
	{
		dbg_error("can't send spi message \n");
		return -1;
	}

#if SPI_DEBUG
	// 打印接收数据
	for (int i = 0; i < size; i++) 
	{
		if (i == 0)
		{
			dbg_printf("recv[%d]: ", size);
		}
		printf("%.2x ", pRxBuf[i]);
	}
	printf("\n");
#endif

	return 0;
}


/// spi1句柄
static TSpiHandler tSpiHandler1 =
{
	//static:
	.name	=	"tSpiHandler1",	        ///< 句柄名称
	.dev_name=	"/dev/spidev32766.0",	///< 设备节点
	.mode	=	SPI_MODE_0,				///< 配置模式(SPI_MODE_0:上升沿采样, SPI_MODE_1：下降沿采样)
	.speed	=	10000000,				///< 波特率 = speed/2   bps
	.bits	=	8,
	.delay  = 0,
	.fd		=	-1,

	.uio_name = "/dev/uio3",         	///< emio中断接口
	.uio_fd   = -1,

	//API:
	.Open	=	OpenHandler,
	.Close 	=	CloseHandler,
	.Lock   =   LockHandler,
	.Unlock =   UnlockHandler,
	.Read 	=	ReadHandler,
	.Write 	=	WriteHandler,
	.Transfer = TransferHandler,
};

/*************************************************************************************//**
*\n 函数名称： SpiOpen()
*\n 功能描述：
*\n            打开SPI接口
*\n 输入参数：
*\n            void  
*\n 输出参数: 
*\n            
*\n 返 回 值: 
*\n           0 成功; -1 失败; -n     错误码   
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.1.16     创建
*****************************************************************************************/
API int SpiOpen(void)
{
	int ret;
	TSpiHandler *this = &tSpiHandler1;
	
	ret = this->Open(this);
	if (ret == -1)
	{
		dbg_error("this->Open(this) \n");
		return -1;
	}
	
	return 0;
}


/*************************************************************************************//**
*\n 函数名称： SpiClose()
*\n 功能描述：
*\n            关闭SPI接口
*\n 输入参数：
*\n            void  
*\n 输出参数: 
*\n            
*\n 返 回 值: 
*\n           0 成功; -1 失败; -n     错误码   
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.1.16     创建
*****************************************************************************************/
API int SpiClose(void)
{
	TSpiHandler *this = &tSpiHandler1;

	this->Close(this);
	return 0;
}

/*************************************************************************************//**
*\n 函数名称： SpiLock()
*\n 功能描述：
*\n            SPI互斥锁，上锁
*\n 输入参数：
*\n            void  
*\n 输出参数: 
*\n            
*\n 返 回 值: 
*\n           0 成功; -1 失败; -n     错误码   
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.3.15     创建
*****************************************************************************************/
API int SpiLock(void)
{
	int ret;
	TSpiHandler *this = &tSpiHandler1;

	ret = this->Lock(this);
	return ret;
}

/*************************************************************************************//**
*\n 函数名称： SpiUnlock()
*\n 功能描述：
*\n            spi互斥锁，解锁
*\n 输入参数：
*\n            void  
*\n 输出参数: 
*\n            
*\n 返 回 值: 
*\n           0 成功; -1 失败; -n     错误码   
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.3.15     创建
*****************************************************************************************/
API int SpiUnlock(void)
{
	int ret;
	TSpiHandler *this = &tSpiHandler1;

	ret = this->Unlock(this);
	return ret;
}


/*************************************************************************************//**
*\n 函数名称： SpiTransfer()
*\n 功能描述：
*\n            同时发送/接收数据
*\n 输入参数：
*\n            uint8_t *TxBuf  		 : 发送数据
*\n            int len               : 收发长度
*\n 输出参数: 
*\n            uint8_t *RxBuf        : 接收数据
*\n            
*\n 返 回 值: 
*\n           0 成功; -1 失败; -n     错误码   
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.1.16     创建
*****************************************************************************************/
API int SpiTransfer(uint8_t *pTxBuf, /*OUT*/ uint8_t *pRxBuf, int len)
{
	int ret;
	TSpiHandler *this = &tSpiHandler1;
	
	this->Lock(this);
	ret = this->Transfer(this, pTxBuf, pRxBuf,  len);
	this->Unlock(this);
	if (ret < 0)
	{
		dbg_error("this->Transfer()\n");
		return -1;
	}
	// {TODO ...}

	return 0;
}

/*************************************************************************************//**
*\n 函数名称： SpiWrite()
*\n 功能描述：
*\n            只发送数据，（忽略接收的数据）
*\n 输入参数：
*\n            uint8_t *TxBuf  :发送数据
*\n            int len         :长度
*\n 输出参数: 
*\n            
*\n 返 回 值: 
*\n           0 成功; -1 失败; -n     错误码   
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.1.16     创建
*****************************************************************************************/
API int SpiWrite(uint8_t *TxBuf, int len)
{
	int ret;
	TSpiHandler *this = &tSpiHandler1;

	this->Lock(this);
	ret = this->Write(this, TxBuf, len);
	this->Unlock(this);
	if (ret < 0)
	{
		dbg_error("this->Write()\n");
		return -1;
	}

	return 0;
}


/*************************************************************************************//**
*\n 函数名称： SpiRead()
*\n 功能描述：
*\n            只接收数据，（忽略发送数据，）
*\n 输入参数：
*\n            int len         ：读取数据长度
*\n 输出参数: 
*\n            uint8_t *RxBuf  ：读取数据
*\n            
*\n 返 回 值: 
*\n           0 成功; -1 失败; -n     错误码   
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.1.16     创建
*****************************************************************************************/
API int SpiRead(uint8_t *RxBuf, int len)
{
	int ret;
	TSpiHandler *this = &tSpiHandler1;

	this->Lock(this);
	ret = this->Read(this, RxBuf, len);
	this->Unlock(this);
	if (ret < 0)
	{
		dbg_error("this->Read()\n");
		return -1;
	}
	return 0;
}
#endif


#if 1
/*************************************************************************************//**
*\n 功能描述：
*\n     1. EMIO中断处理函数；配合spi接收数据帧
*\n     2. 通过高优先级任务InterruptHandler()接收中断,并通知接收任务接收数据
*****************************************************************************************/
#define SOC_MCU_GPIO1           (0x90 >> 2)   /* 0x41200090 */
#define SOC_MCU_GPIO1_EN        (0x94 >> 2)   /* 0x41200094 */
#define SOC_MCU_GPIO1_CLEAR     (0x98 >> 2)   /* 0x41200098 */
#define SOC_MCU_GPIO1_CLK       (0xa0 >> 2)   /* 0x412000a0 */


/*************************************************************************************//**
*\n 函数名称： InterruptHandler()
*\n 功能描述：
*\n            中断处理函数,处理emio中断，并通知接收线程读取数据;
*\n 输入参数：
*\n            void *arg  
*\n 输出参数: 
*\n            
*\n 返 回 值: 
*\n           
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.3.16     创建
*****************************************************************************************/
static void *InterruptHandler(void *arg)
{
	static const int irq_on = 1;  
	int cnts = -1;
	TSpiHandler *this = &tSpiHandler1;

	while(1)
	{
	loop1:
		if (this->uio_fd <= 0)
		{
			usleep(5000);
			continue;
		}

		cnts = read(this->uio_fd, &cnts, 4);
		dbg_printf("read(%s)	ok \n", this->uio_name);
		// 清中断
		//fpga_register_set(SOC_MCU_GPIO1_CLEAR, 1);
		write(this->uio_fd, &irq_on, sizeof(irq_on));
		if (cnts != 4)
		{
			dbg_error("read(%s) != 4 \n", this->uio_name);
			usleep(10000);
			continue;
		}

		// 发送消息
		dbg_printf("sem_post(sem) \n");
		sem_post(&(this->sem));
	}

error1:
	pthread_exit(0);
}

static int InterruptOpen(void)
{
	TSpiHandler *this = &tSpiHandler1;

	if (NULL == this->uio_name)
	{
		dbg_error(" handle->uio_name == NULL\n");
		return -1;
	}

	this->uio_fd = open(this->uio_name, O_RDWR);
	if (this->uio_fd <= 0)
	{
		perror(this->uio_name);
		dbg_error("Invalid UIO device file:%s.\n", this->uio_name);
		return -1;
	}
	
	fpga_register_set(SOC_MCU_GPIO1_CLK, 50); // 中断脉冲宽度min=50*10uS;
	fpga_register_set(SOC_MCU_GPIO1_EN, 1);   // 使能EMIO中断
	
	dbg_printf("open(%s) == %d ok\n", this->uio_name, this->uio_fd);
	return 0;
}

static int InterruptClose(void)
{
	TSpiHandler *this = &tSpiHandler1;
	
	fpga_register_set(SOC_MCU_GPIO1_EN, 0); // 关闭EMIO中断

	if (this->uio_fd > 0)
	{
		close(this->uio_fd);
		this->uio_fd = 0;
	}

	return 0;
}

static int InterruptWait(void)
{
	TSpiHandler *this = &tSpiHandler1;
	
	sem_wait(&(this->sem));
	return 0;
}

static int InterruptInit(void)
{
	int ret;
	TSpiHandler *this = &tSpiHandler1;

	// 设置spi中断线程采用RR实时调度策略
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
	pthread_attr_setschedpolicy(&attr, SCHED_RR);  // 采用RR调度策略
	struct sched_param param;
	param.sched_priority = 30;                     // 优先级定义为30
	pthread_attr_setschedparam(&attr, &param);


	sem_init(&this->sem, 0, 0);
	ret = InterruptOpen();
	if (ret < 0)
	{
		dbg_error("InterruptOpen(%s) \n", this->uio_name);
		return -1;
	}
	dbg_printf("InterruptOpen(%s) ok\n", this->uio_name);

	// 中断处理线程
	static pthread_t tid;
	ret = pthread_create(&tid, &attr, InterruptHandler, NULL);
	if(0 != ret)
	{
		perror("pthread_create() error \n");
		printf("pthread_create error : %s\n", strerror(errno));
		return (-1);
	}
	// usleep(10*1000);

	dbg_printf("%s() ok\n", __func__);
	return 0;
}

static int InterruptUninit(void)
{
	InterruptClose();
	return 0;
}
#endif



#define ISO_LAYER3_NETWORK   3
#if     ISO_LAYER3_NETWORK
/**************************************************************************************************
* 内容说明：
*   1.该部分解析spi网路层协议（ISO layer3 network）
*   2.接口包括3个交互流程的接口： 发送流程，接收流程， 交互应答流程；
*   
***************************************************************************************************/
#define INDEX_BEGIN       8
#define INDEX_LENGTH     9
#define INDEX_TYPE       12
#define INDEX_SN         13
#define INDEX_DATA       SIZE_OF_SPI_FRAME_HEAD

// 网络层协议数据结构
typedef struct TLayer3Handler
{
	char   *name;
	int    fd;
	pthread_mutex_t   mutex;
	
	uint8_t rxBuffer[BUFFER_MAX_SIZE];
	uint8_t txBuffer[BUFFER_MAX_SIZE];
	uint8_t iSn;
	
	//public:
	int (*Lock)    (struct TLayer3Handler *this);
	int (*Unlock)  (struct TLayer3Handler *this);
	int (*Init)    (struct TLayer3Handler *this);
	int (*Uninit)  (struct TLayer3Handler *this);
} TLayer3Handler;

// 打开
static int TLayer3HandlerInit(TLayer3Handler *this)
{
	int ret;
	if (this->fd > 0)
		return 0;

	this->fd = 0xffff;
	ret = pthread_mutex_init(&this->mutex, NULL);
	if (ret != 0)
	{
		dbg_error("pthread_mutex_init(): %s\n", strerror(errno));
		this->fd = -1;
		return -1;
	}

	return 0;
}

/// 关闭
static int TLayer3HandlerUninit(TLayer3Handler *this)
{
	if (this->fd > 0)
	{
		this->fd = -1;
		pthread_mutex_destroy(&this->mutex);
	}
	return 0;
}

///  上锁
static int TLayer3HandlerLock(TLayer3Handler *this)
{
	int ret;
	if (this->fd <= 0)
	{
		dbg_error("this->fd <= 0 \n");
		return -1;
	}
	
	ret = pthread_mutex_lock(&this->mutex);
	if (ret != 0)
		return -1;
		
	return  0;
}

/// 开锁
static int TLayer3HandlerUnlock(TLayer3Handler *this)
{
	int ret;
	if (this->fd <= 0)
	{
		dbg_error("this->fd <= 0 \n");
		return -1;
	}
	
 	ret = pthread_mutex_unlock(&this->mutex);
 	if (ret != 0)
 		return -1;
 		
	return  0;
}

static TLayer3Handler  tLayer3Handler1 =
{
	.name  = "tLayer3Handler1",
	.fd    = -1,
	
	.Lock   = TLayer3HandlerLock,
	.Unlock = TLayer3HandlerUnlock,
	.Init   = TLayer3HandlerInit,
	.Uninit = TLayer3HandlerUninit,
};


/*************************************************************************************//**
*\n 函数名称： Crc16()
*\n 功能描述：
*\n            计算CRC16
*\n 输入参数：
*\n            uint16_t InitValue   :初值，默认为0;
*\n            char  * pbyData      :数据;
*\n            int iLen          	:长度; 
*\n 输出参数: 
*\n            
*\n 返 回 值:   CRC16的值 
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.3.16     创建
*****************************************************************************************/
static uint16_t Crc16(uint16_t InitValue, char  * pbyData, int iLen)
{
	
	#define POLYNOME            0x1021  //  多项式
	#define HIGH_ORDER          (1)  // WordByte.pbyByte 高字节 (根据大尾端、小尾端调整)
	#define LOW_ORDER           (0)  // WordByte.pbyByte 低字节
	
	typedef union
	{
		char 	 pbyByte[2];
		uint16_t  u16Word;
	}WordByte;


	register uint16_t u16Crc = InitValue; // 初值 
	register int i, j;
	WordByte uWordByte;
	for(i = 0; i < iLen; i ++)
	{
        uWordByte.u16Word = u16Crc;
        uWordByte.pbyByte[HIGH_ORDER] ^= pbyData[i];
        for (j=0; j<8; j++)
        {
            if (uWordByte.pbyByte[HIGH_ORDER] & 0x80)
            {
                uWordByte.u16Word = (uWordByte.u16Word << 1) ^ POLYNOME;
            }
            else
            {
                uWordByte.u16Word <<= 1;
            }
        }
        u16Crc = uWordByte.u16Word;
	}
	return (u16Crc);
}





/*************************************************************************************//**
*\n 函数名称： Layer3RecvFrame()
*\n 功能描述：
*\n            网络层接收函数,
*\n            1. 中断接收MCU主动发送的数据帧；
*\n            2. 解码/校验,并取出有效数据(应用层数据)
*\n            3. 首帧iSize填0,则发送同步帧获取首帧长度，并接收首帧；
*\n            4. 根据返回值(下一帧长度),决定是否读取下一帧：
*\n               返回值大于0，表示还有下一帧，需要继续读取下一帧；
*\n 输入参数：
*\n            char RecvBuffer[]  : 接收buffer
*\n            size_t iBufferSize : 接收buffer的长度
*\n            size_t iSize       : 接收长度(应用层数据长度),首帧填0
*\n 输出参数: 
*\n            char RecvBuffer[]  : 接收数据(应用层数据)
*\n            
*\n 返 回 值:  下一帧长度(应用层数据长度)
*\n             0: 没有下一帧   
*\n            -n: 错误码   
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.3.16     创建
*****************************************************************************************/
static int Layer3RecvFrame(  uint8_t RecvBuffer[], size_t iBufferSize, 
						  size_t iSize)
{
	int ret;
	uint16_t iCrcl, iCrc2;
	int iFrameSize, iNextFrameSize;
	TLayer3Handler *this = &tLayer3Handler1;
	
	this->Lock(this);   // 加锁

	// 1. 接收状态帧（固定22bytes=12Bytes同步序列 + 10Bytes帧);
	if (iSize == 0)
	{
		memset(this->rxBuffer, 0, sizeof(this->rxBuffer));
		ret = SpiRead(this->rxBuffer, 22);
		if (ret < 0)
		{
			dbg_error("SpiRead(this->rxBuffer, 22) \n");
			ret = -1;
			goto exit1;
		}
		// 检测帧头
		if ((0xaa != this->rxBuffer[INDEX_BEGIN-1]) || (0x55 != this->rxBuffer[INDEX_BEGIN]))
		{
			dbg_error("(0xaa != RecvBuffer[7]) || (0x55 != RecvBuffer[8])\n");
			ret = -1;
			goto exit1;
		}
		// 长度检测
		iFrameSize	    = this->rxBuffer[INDEX_LENGTH];
		iFrameSize	   |= ((int)this->rxBuffer[INDEX_LENGTH+1] << 8)  & 0x0f00;
		iNextFrameSize  = this->rxBuffer[INDEX_LENGTH+2];
		iNextFrameSize |= ((int)this->rxBuffer[INDEX_LENGTH+1] << 4)  & 0x0f00;
		if (10 != iFrameSize)
		{
			dbg_error("10 != iFrameSize[=%d]\n", iFrameSize);
			ret = -1;
			goto exit1;
		}
		// type检测
		if (1 != this->rxBuffer[INDEX_TYPE])
		{
			dbg_error("%s.rxBuffer[INDEX_TYPE] != 1 \n", this->name);
			ret = -1;
			goto exit1;
		}
		// crc校验
		iCrcl = Crc16(0, &(this->rxBuffer[INDEX_BEGIN]), iFrameSize-2);
		iCrc2 = ((uint16_t)this->rxBuffer[INDEX_BEGIN+iFrameSize-2]) +
			   (((uint16_t)this->rxBuffer[INDEX_BEGIN+iFrameSize-1]) << 8);
		if (iCrcl != iCrc2)
		{
			dbg_error("iCrcl[=0x%04x] != iCrc2[=0x%04x] \n", iCrcl, iCrc2);
			ret = -1;
			goto exit1;
		}
	}
	else
	{
		iNextFrameSize = iSize + 8;
	}

	// 2. 接收数据帧
	{
		iFrameSize = iNextFrameSize;
		if (iFrameSize < 8)
		{
			dbg_error("iFrameSize[=0x%04x] < 8 \n", iFrameSize);
			ret = -1;
			goto exit1;
		}
		memset(this->rxBuffer, 0, sizeof(this->rxBuffer));
		ret = SpiRead(this->rxBuffer, iFrameSize+12);
		if (ret < 0)
		{
			dbg_error("SpiRead(this->rxBuffer, %d) \n", iFrameSize+12);
			ret = -1;
			goto exit1;
		}
		// 检测帧头
		
		// 检测帧头
		uint8_t *pFrame = NULL;
		for (int i = 1; i < 16; ++i)
		{
			if ((0xaa == this->rxBuffer[i-1]) && (0x55 == this->rxBuffer[i]))
			{
				pFrame = & (this->rxBuffer[i-8]);  //帧头指针
				goto next1;
			}
		}
		dbg_error("not find frame head  0xaa,0x55 \n");
		ret = -1;
		goto exit1;
		
		// 长度检测
		int iPkgSize;
next1:
		iPkgSize	    = pFrame[INDEX_LENGTH];
		iPkgSize	   |= ((int)pFrame[INDEX_LENGTH+1] << 8)  & 0x0f00;
		iNextFrameSize  = pFrame[INDEX_LENGTH+2];
		iNextFrameSize |= ((int)pFrame[INDEX_LENGTH+1] << 4)  & 0x0f00;
		if (iPkgSize != iFrameSize)
		{
			dbg_error("iPkgSize[=%d] != iFrameSize[=%d] \n", iPkgSize, iFrameSize);
			// dbg_info(this->rxBuffer, iFrameSize+12, "rxBuffer[%d]=", iFrameSize+12);
			ret = -1;
			goto exit1;
		}

		// type检测
//		if (0 != pFrame[INDEX_TYPE])
//		{
//			dbg_error("%pFrame[INDEX_TYPE] != 0 \n");
//			ret = -1;
//			goto exit1;
//		}
		// crc校验
		iCrcl = Crc16(0, &(pFrame[INDEX_BEGIN]), iFrameSize-2);
		iCrc2 = ((uint16_t)pFrame[INDEX_BEGIN+iFrameSize-2]) +
			   (((uint16_t)pFrame[INDEX_BEGIN+iFrameSize-1]) << 8);
		if (iCrcl != iCrc2)
		{
			dbg_error("iCrcl[=0x%04x] != iCrc2[=0x%04x] \n", iCrcl, iCrc2);
			ret = -1;
			goto exit1;
		}

		// 返回有效数据(应用层数据), 下次读取的数据长度
		if (iSize > iBufferSize)
		{
			dbg_error("iSize[=0x%04x] > iBufferSize[=0x%04x] \n", iSize, iBufferSize);
			ret = -1;
			goto exit1;
		}
		memcpy(RecvBuffer, &(pFrame[INDEX_DATA]), iSize);
		ret = (iNextFrameSize > 8) ?  (iNextFrameSize - 8) : 0;
	}
	
exit1:
	this->Unlock(this);  //解锁
	return ret;
}


/*************************************************************************************//**
*\n 函数名称： SpiRecvTask()
*\n 功能描述：
*\n            接收线程，阻塞等待接收MCU主动发送给fpga的数据帧
*\n 输入参数：
*\n            void *arg  
*\n 输出参数: 
*\n            
*\n 返 回 值: 
*\n          
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.3.16     创建
*****************************************************************************************/
static void *SpiRecvTask(void *arg)
{
	static uint8_t RecvBuffer[BUFFER_MAX_SIZE];
	int ret;
	int iSize, iNextFrameSize;

	while(1)
	{
	loop1:
		InterruptWait();  // 等待IO中断信号
		dbg_printf("sem_wait() ok\n");

		// 接收第1 ~ n数据帧
		iSize = 0;
		do{
			memset(RecvBuffer, 0, sizeof(RecvBuffer));
			iNextFrameSize = Layer3RecvFrame(RecvBuffer, sizeof(RecvBuffer), iSize);
			dbg_printf("iSize = %d\n", iSize);
			if (iNextFrameSize < 0)
			{
				dbg_error("Layer3RecvFrame() < 0\n");
				goto loop1;
			}
			/* {TODO : 处理应用层数据 } */
			if (NULL != tCallback_UdsProcess1)
			{
				ret = tCallback_UdsProcess1(RecvBuffer, iSize);
				if (ret < 0)
				{
					dbg_error("tCallback_UdsProcess1(RecvBuffer, iSize)<0\n");
				}
			}
			
			iSize = iNextFrameSize;
		} while(iSize > 0);
	}

exit1:
	pthread_exit(0);
}




/**************************************************************************************************
* 全局函数声明、定义
***************************************************************************************************/
API void Msleep(unsigned long s,  unsigned long ms)
{
    struct timeval tv;

    tv.tv_sec  = s;
    tv.tv_usec = 1000 * ms;
    select(0, NULL, NULL, NULL, &tv);
}



/*************************************************************************************//**
*\n 函数名称： Layer3RegisterUdsProcess()
*\n 功能描述：
*\n            注册uds诊断协议的处理函数
*\n            
*\n 输入参数：
*\n            TCallback_UdsProcess pFunc : 回调函数指针
*\n 输出参数: 
*\n            
*\n 返 回 值: 
*\n           0 成功; -1 失败; -n     错误码   
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.3.16     创建
*****************************************************************************************/
API int Layer3RegisterUdsProcess(TCallback_UdsProcess pFunc)
{
	tCallback_UdsProcess1 = pFunc;
	return 0;
}


/*************************************************************************************//**
*\n 函数名称： Layer3WriteFrame()
*\n 功能描述：
*\n            网络层协议编码/发送
*\n            1. 对应用层数据编码,打包成网络层的数据帧
*\n            2. 调用物理层接口发送数据
*\n            
*\n 输入参数：
*\n            size_t TxBuffer : 发送数据(应用层数据)
*\n            size_t iSize    : 发送长度(bytes)
*\n 输出参数: 
*\n            
*\n 返 回 值: 
*\n           0 成功; -1 失败; -n     错误码   
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.3.16     创建
*****************************************************************************************/
API int Layer3WriteFrame(uint8_t txBuffer[], size_t iSize)
{
	int ret;
	uint16_t iCrcl, iCrc2;
	size_t   iFrameSize, iNextFrameSize;
	
	static uint8_t iHead[] = 
	{   0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 
		/*len*/ 0,0,0, /*type*/ 0, /*sn*/ 0
	};
	static uint8_t iTail[] = 
	{
		 0x55, 0x55, 0x55, 0x55
	};
	TLayer3Handler *this = &tLayer3Handler1;
	
	this->Lock(this);   // 加锁
	
	// 1. 编码数据帧;
	// 同步序列1
	memset(this->txBuffer, 0, sizeof(this->txBuffer));
	memcpy(this->txBuffer, iHead, sizeof(iHead));
	// 计算长度
	iNextFrameSize = 0;
	iFrameSize = iSize + 8;
	this->txBuffer[INDEX_LENGTH+0]  = iFrameSize;
	this->txBuffer[INDEX_LENGTH+1]  = (iFrameSize >> 8) & 0x0f | (iNextFrameSize >> 4) & 0xf0;
	this->txBuffer[INDEX_LENGTH+2]  = iNextFrameSize;
	this->txBuffer[INDEX_SN] = this->iSn++;
	// 填充数据
	memcpy(&(this->txBuffer[INDEX_DATA]), txBuffer, iSize);
	// 计算crc16
	iCrcl = Crc16(0, &(this->txBuffer[INDEX_BEGIN]), iFrameSize-2);
	this->txBuffer[INDEX_BEGIN+iFrameSize-2]  = iCrcl;
	this->txBuffer[INDEX_BEGIN+iFrameSize-1]  = iCrcl >> 8;
	// 尾部同步序列
	memcpy(&(this->txBuffer[INDEX_BEGIN+iFrameSize]), iTail, sizeof(iTail));

	///< 2. 调用物理链路层接口发送数据帧
	ret = SpiWrite(this->txBuffer, iFrameSize+12);
	if (ret < 0)
	{
		dbg_error("SpiWrite(txBuffer[%d]) \n", iFrameSize+12);
		//return -1;
		ret = -1;	
		goto exit1;
	}
	ret = 0;

exit1:
	this->Unlock(this);  //解锁
	return ret;
}




/*************************************************************************************//**
*\n 函数名称： Layer3ReadFrame()
*\n 功能描述：
*\n            网络层读取函数（fpga读取MCU的参数）,
*\n            1. 调用物理层接口读取数据;
*\n            2. 解码/校验,并取出有效数据(应用层数据)
*\n            
*\n 输入参数：
*\n            char RecvBuffer[]  : 接收buffer
*\n            size_t iBufferSize : 接收buffer的长度
*\n            size_t iSize       : 接收长度(应用层数据长度)
*\n 输出参数: 
*\n            char RecvBuffer[]  : 接收数据(应用层数据)
*\n            
*\n 返 回 值:  下一帧长度
*\n             0: 没有下一帧   
*\n            -n: 错误码   
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01   罗先能        2020.3.16     创建
*****************************************************************************************/
API int Layer3ReadFrame(  uint8_t RecvBuffer[], size_t iBufferSize, 
						  size_t iSize)
{
	int ret;
	uint16_t iCrcl, iCrc2;
	int iFrameSize, iNextFrameSize;
	static uint8_t CmdBuffer[22] = { 
		0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 
		0x55, /*len*/ 0,0,0, /*type*/ 0x02, /*sn*/ 0, /*data*/ 0,0,/*crc16*/ 0, 0,  
		0x55,0x55,0x55,0x55
	};
	TLayer3Handler *this = &tLayer3Handler1;
	
	this->Lock(this);   // 加锁

	// 1. 发送读取命令帧（固定22bytes);
	{
		// 同步序列1
		memset(this->txBuffer, 0, sizeof(this->txBuffer));
		memcpy(this->txBuffer, CmdBuffer, sizeof(CmdBuffer));
		// 长度
		iFrameSize = 10;
		iNextFrameSize = iSize + 8;
		this->txBuffer[INDEX_LENGTH+0]	= iFrameSize;
		this->txBuffer[INDEX_LENGTH+1]	= (iFrameSize >> 8) & 0x0f | (iNextFrameSize >> 4) & 0xf0;
		this->txBuffer[INDEX_LENGTH+2]	= iNextFrameSize;
		this->txBuffer[INDEX_TYPE] = 0x02;
		this->txBuffer[INDEX_SN]   = this->iSn++;
		// 数据
		this->txBuffer[INDEX_DATA] = 0x01;   //任务ID
		// 计算crc16
		iCrcl = Crc16(0, &(this->txBuffer[INDEX_BEGIN]), iFrameSize-2);
		this->txBuffer[INDEX_BEGIN+iFrameSize-2]  = iCrcl;
		this->txBuffer[INDEX_BEGIN+iFrameSize-1]  = iCrcl >> 8;
		
		// 调用物理链路层接口发送命令帧
		//ret = SpiWrite(this->txBuffer, iFrameSize+12);
		ret = SpiTransfer(this->txBuffer, this->rxBuffer, iFrameSize+12);
		if (ret < 0)
		{
			dbg_error("SpiWrite(txBuffer[%d]) \n", iFrameSize+12);
			ret = -1;
			goto exit1;
		}
	}

	//uint64_t val1 = cpu_get_time_now_ms();
	//Msleep(0,5);
	usleep(10*1000);
	//uint64_t val2 = cpu_get_time_now_ms();
	//dbg_printf("Msleep(%d ms)\n", (int)(val2 - val1));

	// 2. 读取数据帧
	{
		// 同步序列1
		memset(this->txBuffer, 0, sizeof(this->txBuffer));
		memcpy(this->txBuffer, CmdBuffer, INDEX_DATA);
		// 长度
		iFrameSize = iSize + 8;
		iNextFrameSize = 0;
		this->txBuffer[INDEX_LENGTH+0]	= iFrameSize;
		this->txBuffer[INDEX_LENGTH+1]	= (iFrameSize >> 8) & 0x0f | (iNextFrameSize >> 4) & 0xf0;
		this->txBuffer[INDEX_LENGTH+2]	= iNextFrameSize;
		this->txBuffer[INDEX_TYPE] = 0x00;  
		this->txBuffer[INDEX_SN]   = this->iSn++;
		
		// 数据
		this->txBuffer[INDEX_DATA]   = this->txBuffer[INDEX_DATA+1] = 0xff;
		this->txBuffer[INDEX_DATA+2] = 0x01;             // ID
		this->txBuffer[INDEX_DATA+3] = 0x01;             // TYPE
		this->txBuffer[INDEX_DATA+4] = (iSize-6) << 8;   // Length
		this->txBuffer[INDEX_DATA+5] = (iSize-6);  
		
		// 计算crc16
		iCrcl = Crc16(0, &(this->txBuffer[INDEX_BEGIN]), iFrameSize-2);
		this->txBuffer[INDEX_BEGIN+iFrameSize-2]  = iCrcl;
		this->txBuffer[INDEX_BEGIN+iFrameSize-1]  = iCrcl >> 8;
		// 同步序列2
		memset(&(this->txBuffer[INDEX_BEGIN+iFrameSize]), 0x55, 4);
		
		// 调用物理链路层接口发送命令帧、接收数据帧
		memset(this->rxBuffer, 0, sizeof(this->rxBuffer));
		//ret = SpiRead(this->rxBuffer, iFrameSize+12);
		ret = SpiTransfer(this->txBuffer, this->rxBuffer, iFrameSize+12);
		if (ret < 0)
		{
			dbg_error("SpiRead(this->rxBuffer, %d) \n", iFrameSize+12);
			ret = -1;
			goto exit1;
		}
		
		// 检测帧头
		uint8_t *pFrame = NULL;
		for (int i = 1; i < 16; ++i)
		{
			if ((0xaa == this->rxBuffer[i-1]) && (0x55 == this->rxBuffer[i]))
			{
				pFrame = & (this->rxBuffer[i-8]);  //帧头指针
				goto next1;
			}
		}
		dbg_error("not find frame head  0xaa,0x55 \n");
		ret = -1;
		goto exit1;
		
		// 长度检测
		int iPkgSize;
next1:
		iPkgSize	    = pFrame[INDEX_LENGTH];
		iPkgSize	   |= ((int)pFrame[INDEX_LENGTH+1] << 8)  & 0x0f00;
		iNextFrameSize  = pFrame[INDEX_LENGTH+2];
		iNextFrameSize |= ((int)pFrame[INDEX_LENGTH+1] << 4)  & 0x0f00;
		if (iPkgSize != iFrameSize)
		{
			dbg_error("iPkgSize[=%d] != iFrameSize[=%d] \n", iPkgSize, iFrameSize);
			// dbg_info(this->rxBuffer, iFrameSize+12, "rxBuffer[%d]=", iFrameSize+12);
			ret = -1;
			goto exit1;
		}
		// type检测
//		if (0 != pFrame[INDEX_TYPE])
//		{
//			dbg_error("pFrame[INDEX_TYPE] != 0 \n");
//			ret = -1;
//			goto exit1;
//		}
		// crc校验
		iCrcl = Crc16(0, &(pFrame[INDEX_BEGIN]), iFrameSize-2);
		iCrc2 = ((uint16_t)pFrame[INDEX_BEGIN+iFrameSize-2]) +
			   (((uint16_t)pFrame[INDEX_BEGIN+iFrameSize-1]) << 8);
		if (iCrcl != iCrc2)
		{
			dbg_error("iCrcl[=0x%04x] != iCrc2[=0x%04x] \n", iCrcl, iCrc2);
			ret = -1;
			goto exit1;
		}
		// 返回有效数据(应用层数据), 下次读取的数据长度
		if (iSize > iBufferSize)
		{
			dbg_error("iSize[=0x%04x] > iBufferSize[=0x%04x] \n", iSize, iBufferSize);
			ret = -1;
			goto exit1;
		}
		// copy数据
		memcpy(RecvBuffer, &(pFrame[INDEX_DATA]), iSize);
		ret = (iNextFrameSize > 8) ? (iNextFrameSize-8) : 0;
	}

exit1:
	this->Unlock(this);  //解锁
	return ret;
}

/*************************************************************************************//**
*\n 函数名称： Layer3Init()
*\n 功能描述：
*\n            初始化spi网络层
*\n 输入参数：
*\n            void  
*\n 输出参数: 
*\n            
*\n 返 回 值: 
*\n           0 成功; -1 失败; -n     错误码   
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.3.18     创建
*****************************************************************************************/
API int Layer3Init(void)
{
	int ret = 0;
	TLayer3Handler *this = &tLayer3Handler1;

	ret = SpiOpen();  
	if (ret < 0)
	{
		dbg_error("SPI_Open() error \n");
		return -1;
	}
	dbg_printf("SpiOpen() ok\n");
	
	// ret = InterruptInit();
	// if(0 > ret)
	// {
	// 	dbg_error("InterruptInit() < 0\n");
	// 	return (-1);
	// }

	ret = this->Init(this);
	if (ret < 0)
	{
		dbg_error("%s.Init()\n", this->name);
		return -1;
	}
	dbg_printf("this->Init(this) ok\n");

	// static pthread_t recv_tid = 0;
	// ret = pthread_create(&recv_tid, NULL, SpiRecvTask, NULL);
	// if(0 != ret)
	// {
	// 	dbg_error("pthread_create failed : %s\n", strerror(errno));
	// 	return (-1);
	// }
	dbg_printf("Layer3Init() ok\n");
	
	return 0;
}


/*************************************************************************************//**
*\n 函数名称： Layer3Uninit()
*\n 功能描述：
*\n            反初始化spi网络层
*\n 输入参数：
*\n            void  
*\n 输出参数: 
*\n            
*\n 返 回 值: 
*\n           0 成功; -1 失败; -n     错误码   
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2020.3.18     创建
*****************************************************************************************/
API int Layer3Uninit(void)
{
	int ret = 0;
	TLayer3Handler *this = &tLayer3Handler1;
	
	ret = this->Uninit(this);
	if (ret < 0)
	{
		dbg_error("%s.Close()\n", this->name);
		return -1;
	}
	
	ret = InterruptUninit();
	if(0 > ret)
	{
		dbg_error("InterruptInit() < 0\n");
		return (-1);
	}
	
	ret = SpiClose();  
	if (ret < 0)
	{
		dbg_error("SPI_Open() error \n");
		return -1;
	}
	
	return 0;
}
#endif



